package com.cskaoyan.javase.oop2._1extends._8hidden;

/**
 * 属性的隐藏
 * 在上面章节中，我们已经知道，父子类的成员是允许同名的。
 * 那么如果父子类属性同名了，那么不使用super区分，直接访问的效果是什么样的呢？
 *
 * 现在我们直接创建子类对象，使用子类引用接收。
 * 会发现访问的结果是子类中属性的取值，那么父类中的那个成员变量去哪了呢？
 * 首先它肯定是存在的，这一点随便写一个父类成员变量的Getter方法就可以验证了。
 *
 * 但是当使用子类对象名点访问这个同名成员变量时,访问的结果是子类中的结果
 * 这种现在就称之为属性的隐藏
 *
 * 这节重点是研究"对象名点"访问成员变量的机制
 * 研究这个访问机制从两个角度:
 *      1.研究"对象名点"访问成员变量的访问范围
 *      2.研究"对象名点"访问成员变量的访问结果
 *
 * 当然研究之前,我们要知道,当存在父子类继承关系时,创建对象有三种形式:
 *      1.创建子类对象,用子类引用接收
 *      2.创建父类对象,用父类引用接收
 *      3.创建子类对象,用父类引用接收
 *
 * 首先研究访问范围:
 *      1.创建子类对象,用子类引用接收
 *          访问范围是 父类 + 子类
 *          父类和子类中的成员变量都可以访问
 *
 *      2.创建父类对象,用父类引用接收
 *          访问范围就只有父类
 *
 *      3.创建子类对象,用父类引用接收
 *          访问范围就只有父类
 * 综上,"对象名点"访问成员变量的访问范围要看引用的数据类型
 * 具体来说
 * 如果引用是一个父类类型,那就只能访问父类中的成员变量
 * 如果引用是一个子类类型,那就能够访问子类 + 父类
 *
 * 在Java中，访问范围是可以往上查找父类的，但不能往下找子类。
 * 子类知道自己的"爸爸"是谁，但"爸爸"并不知道它有这个"儿子"，甚至都不知道自己有几个"儿子"，或者有没有"儿子"。
 *
 * 在Java当中，对象名点访问成员变量的范围是编译器决定的，是一个编译上的概念。
 * 所以根据引用的类型就能够确定访问范围了
 * 因为引用数据类型的声明就是告诉编译器变量的数据类型
 *
 * 接下来研究"对象名点"访问成员变量的访问结果,仍然从三个角度:
 *      1.创建子类对象,用子类引用接收
 *          结果肯定是子类中的取值
 *
 *      2.创建父类对象,用父类引用接收
 *          结果肯定是父类中的取值
 *
 *      3.创建子类对象,用父类引用接收
 *          结果是父类中的取值
 *
 * 综上所述,"对象名点"访问成员变量的访问也是看引用的
 *
 * 以上,大总结:
 * "对象名点"访问成员变量无论是访问范围还是访问结果
 * 都要看引用的类型
 *
 * @since 11:12
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        /*Son s = new Son();
        System.out.println(s.num);
        System.out.println(s.getNum());*/

        // 1.创建子类对象,用子类引用接收
        Son s = new Son();
        System.out.println("son num = " + s.num);
        System.out.println(s.sonNum);
        System.out.println(s.fatherNum);
        // 2.创建父类对象,用父类引用接收
        Father f = new Father();
        System.out.println(f.fatherNum);
        System.out.println("father num = " + f.num);
        // f.son
        // 3.创建子类对象,用父类引用接收
        Father fs = new Son();
        // System.out.println(fs.fatherNum);
        // fs.sonNum.sout
        // fs想要访问子类成员变量需要强转,不能直接访问
        // ((Son) fs).sonNum
        System.out.println("fs num = " + fs.num);
    }
}

class Father {
    int num = 10;
    int fatherNum = 20;
    /*public int getNum() {
        return num;
    }*/
}

class Son extends Father {
    int num = 100;
    int sonNum = 200;
}